"""
用户评分评论接口测试
测试用户评分评论的增删改查功能
"""

import requests
import json
import time

base_url = "http://localhost:8080/api"
ratings_url = f"{base_url}/ratings"
users_url = f"{base_url}/users"


def login_user(username, password):
    """用户登录并返回token"""
    login_data = {"username": username, "password": password}
    response = requests.post(
        f"{users_url}/login",
        json=login_data,
        headers={"Content-Type": "application/json"},
    )
    if response.status_code == 200:
        return response.json().get("token")
    else:
        print(f"登录失败: {response.json()}")
        return None


def register_user(username, password):
    """用户注册"""
    register_data = {"username": username, "password": password}
    response = requests.post(
        f"{users_url}/register",
        json=register_data,
        headers={"Content-Type": "application/json"},
    )
    return response.status_code == 200


def test_ratings_info():
    """测试获取评分评论管理接口信息"""
    print("=== 测试获取评分评论管理接口信息 ===")

    try:
        response = requests.get(f"{ratings_url}/")

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 获取评分评论接口信息成功")
            return True
        else:
            print("❌ 获取评分评论接口信息失败")
            return False

    except Exception as e:
        print(f"❌ 获取评分评论接口信息请求异常: {e}")
        return False


def test_add_rating(token, book_id=1, rating=4.5, comment="这本书很好看"):
    """测试添加/修改评分评论"""
    print(f"\n=== 测试添加/修改评分评论 (book_id: {book_id}, rating: {rating}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    data = {"book_id": book_id, "rating": rating, "comment": comment}

    try:
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 添加/修改评分评论成功")
            return True
        else:
            print("❌ 添加/修改评分评论失败")
            return False

    except Exception as e:
        print(f"❌ 添加/修改评分评论请求异常: {e}")
        return False


def test_update_rating(token, book_id=1, rating=3.5, comment="修改后的评论内容"):
    """测试修改现有评分评论"""
    print(f"\n=== 测试修改现有评分评论 (book_id: {book_id}, rating: {rating}) ===")

    return test_add_rating(token, book_id, rating, comment)


def test_get_book_ratings(token=None, book_id=1, page=1, limit=10):
    """测试获取图书评分评论列表"""
    print(
        f"\n=== 测试获取图书评分评论列表 (book_id: {book_id}, page: {page}, limit: {limit}) ==="
    )

    headers = {"Content-Type": "application/json"}
    if token:
        headers["Authorization"] = f"Bearer {token}"

    try:
        response = requests.get(
            f"{ratings_url}/list?book_id={book_id}&page={page}&limit={limit}",
            headers=headers,
        )

        print(f"状态码: {response.status_code}")
        response_data = response.json()
        print(f"响应内容: {json.dumps(response_data, ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 获取图书评分评论列表成功")
            print(f"总评论数: {response_data.get('total', 0)}")
            print(f"当前页评论数量: {len(response_data.get('ratings_list', []))}")
            return response_data
        else:
            print("❌ 获取图书评分评论列表失败")
            return False

    except Exception as e:
        print(f"❌ 获取图书评分评论列表请求异常: {e}")
        return False


def test_delete_rating(token, book_id=1):
    """测试删除评分评论"""
    print(f"\n=== 测试删除评分评论 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.delete(
            f"{ratings_url}/delete?book_id={book_id}", headers=headers
        )

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 200:
            print("✅ 删除评分评论成功")
            return True
        elif response.status_code == 400 and "未找到" in response.json().get(
            "message", ""
        ):
            print("✅ 未找到要删除的评论（预期行为）")
            return True
        else:
            print("❌ 删除评分评论失败")
            return False

    except Exception as e:
        print(f"❌ 删除评分评论请求异常: {e}")
        return False


def test_delete_nonexistent_rating(token, book_id=999):
    """测试删除不存在的评分评论"""
    print(f"\n=== 测试删除不存在的评分评论 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.delete(
            f"{ratings_url}/delete?book_id={book_id}", headers=headers
        )

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 400 and "未找到" in response.json().get(
            "message", ""
        ):
            print("✅ 删除不存在评论验证成功")
            return True
        else:
            print("❌ 删除不存在评论验证失败")
            return False

    except Exception as e:
        print(f"❌ 删除不存在评论请求异常: {e}")
        return False


def test_unauthorized_access():
    """测试未授权访问"""
    print("\n=== 测试未授权访问 ===")

    try:
        # 测试没有token的情况
        data = {"book_id": 1, "rating": 4.5, "comment": "测试评论"}
        headers = {"Content-Type": "application/json"}
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"无token添加评论 - 状态码: {response.status_code}")

        response = requests.delete(f"{ratings_url}/delete?book_id=1", headers=headers)
        print(f"无token删除评论 - 状态码: {response.status_code}")

        # 测试无效token的情况
        headers = {
            "Authorization": "Bearer invalid_token",
            "Content-Type": "application/json",
        }
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"无效token添加评论 - 状态码: {response.status_code}")

        if response.status_code == 401:
            print("✅ 未授权访问验证成功")
            return True
        else:
            print("❌ 未授权访问验证失败")
            return False

    except Exception as e:
        print(f"❌ 未授权访问测试异常: {e}")
        return False


def test_invalid_parameters(token):
    """测试无效参数"""
    print("\n=== 测试无效参数 ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        # 测试缺少book_id
        data = {"rating": 4.5, "comment": "测试评论"}
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"缺少book_id - 状态码: {response.status_code}")

        # 测试缺少rating
        data = {"book_id": 1, "comment": "测试评论"}
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"缺少rating - 状态码: {response.status_code}")

        # 测试无效rating范围
        data = {"book_id": 1, "rating": 15.0, "comment": "测试评论"}
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"无效rating范围 - 状态码: {response.status_code}")

        # 测试负数rating
        data = {"book_id": 1, "rating": -1.0, "comment": "测试评论"}
        response = requests.post(f"{ratings_url}/update", json=data, headers=headers)
        print(f"负数rating - 状态码: {response.status_code}")

        # 测试缺少book_id参数（删除时）
        response = requests.delete(f"{ratings_url}/delete", headers=headers)
        print(f"删除时缺少book_id - 状态码: {response.status_code}")

        # 测试缺少book_id参数（查询时）
        response = requests.get(f"{ratings_url}/list", headers=headers)
        print(f"查询时缺少book_id - 状态码: {response.status_code}")

        if response.status_code == 422:  # FastAPI参数验证错误
            print("✅ 无效参数验证成功")
            return True
        else:
            print("❌ 无效参数验证失败")
            return False

    except Exception as e:
        print(f"❌ 无效参数测试异常: {e}")
        return False


def test_rating_edge_cases(token):
    """测试评分边界情况"""
    print("\n=== 测试评分边界情况 ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    # 测试最小值和最大值
    edge_cases = [
        (0.0, "最低评分"),
        (5.0, "最高评分"),
        (2.5, "中等评分"),
        (4.9, "接近最高评分"),
    ]

    success_count = 0

    for rating, description in edge_cases:
        print(f"\n测试{description}: {rating}")
        if test_add_rating(
            token, book_id=100, rating=rating, comment=f"{description}测试"
        ):
            success_count += 1

    print(f"✅ 边界情况测试完成，成功: {success_count}/{len(edge_cases)}")
    return success_count == len(edge_cases)


def test_multiple_users_rating_same_book():
    """测试多个用户对同一本书评分"""
    print("\n=== 测试多个用户对同一本书评分 ===")

    # 创建两个测试用户
    timestamp = int(time.time())
    user1_name = f"rating_test_user1_{timestamp}"
    user2_name = f"rating_test_user2_{timestamp}"
    password = "123456"

    # 注册用户
    if not register_user(user1_name, password):
        print("❌ 用户1注册失败")
        return False

    if not register_user(user2_name, password):
        print("❌ 用户2注册失败")
        return False

    # 登录用户
    token1 = login_user(user1_name, password)
    token2 = login_user(user2_name, password)

    if not token1 or not token2:
        print("❌ 用户登录失败")
        return False

    book_id = 200

    # 用户1添加评分
    print("\n用户1添加评分:")
    if not test_add_rating(token1, book_id, 4.0, "用户1的评论"):
        return False

    # 用户2添加评分
    print("\n用户2添加评分:")
    if not test_add_rating(token2, book_id, 5.0, "用户2的评论"):
        return False

    # 查看评论列表
    print("\n查看该书的所有评论:")
    result = test_get_book_ratings(book_id=book_id)

    if result and result.get("total", 0) >= 2:
        print("✅ 多用户评分测试成功")
        return True
    else:
        print("❌ 多用户评分测试失败")
        return False


def run_all_ratings_tests():
    """运行所有评分评论测试"""
    print("开始用户评分评论功能测试...")
    print("=" * 80)

    # 测试用户名（使用时间戳确保唯一性）
    username = f"ratings_test_user_{int(time.time())}"
    password = "123456"

    # 1. 注册测试用户
    print(f"注册测试用户: {username}")
    if not register_user(username, password):
        print("❌ 用户注册失败，测试终止")
        return

    # 2. 登录获取token
    print(f"登录测试用户: {username}")
    token = login_user(username, password)
    if not token:
        print("❌ 用户登录失败，测试终止")
        return

    print(f"✅ 获得token: {token[:20]}...")

    # 3. 测试获取评分评论接口信息
    test_ratings_info()

    # 4. 测试未授权访问
    test_unauthorized_access()

    # 5. 测试无效参数
    test_invalid_parameters(token)

    # 6. 测试查看空评论列表
    test_get_book_ratings(book_id=1)

    # 7. 测试添加评分评论
    test_add_rating(token, book_id=1, rating=4.5, comment="第一条评论")
    test_add_rating(token, book_id=2, rating=3.0, comment="第二条评论")
    test_add_rating(token, book_id=3, rating=5.0, comment="第三条评论")

    # 8. 测试修改评分评论
    test_update_rating(token, book_id=1, rating=3.5, comment="修改后的评论")

    # 9. 测试查看评论列表
    test_get_book_ratings(book_id=1)
    test_get_book_ratings(book_id=2)
    test_get_book_ratings(book_id=3)

    # 10. 测试分页功能
    test_get_book_ratings(book_id=1, page=1, limit=5)

    # 11. 测试评分边界情况
    test_rating_edge_cases(token)

    # 12. 测试删除评论
    test_delete_rating(token, book_id=2)

    # 13. 测试删除不存在的评论
    test_delete_nonexistent_rating(token, book_id=999)

    # 14. 验证删除效果
    test_get_book_ratings(book_id=2)

    # 15. 测试多用户评分
    test_multiple_users_rating_same_book()

    # 16. 最终状态验证
    print(f"\n=== 验证最终评分状态 ===")
    test_get_book_ratings(book_id=1)  # 应该有修改后的评论
    test_get_book_ratings(book_id=2)  # 应该为空
    test_get_book_ratings(book_id=3)  # 应该有原始评论

    print("\n" + "=" * 80)
    print("用户评分评论功能测试完成")


if __name__ == "__main__":
    run_all_ratings_tests()
